
/*
1) 所有在类里声明的回调函数必须为静态函数，且只能调用静态变量，所以都传递了this指针
2) 关闭窗口时，先置标志，然后等待所有线程退出，事件处理线程等待其他所有线程退出后退出
3) 相比1.0版本，把取包和解码分为两个线程，转换放在音视频线程中，但是感觉解码和转换放在一起更合适，且帧队列改为转换后帧的队列
*/
#include "player.h"

using namespace player;

#define ASSERT(c)   do{if(c == NULL){printf("%s is NULL\n",#c);return -1;}}while(0);

#if 1

#define dprintf(fmt,args...)    printf(fmt,##args)

#else

#define dprintf(fmt,args...)

#endif

Player::Player(const char *file):
    screenH(0)
    ,screenW(0)
    ,filename(NULL)
    ,isEventClose(true)
    ,pFormatCtx(NULL)
    ,pPacket(NULL)
    ,pCodec(NULL)
    ,isReadPackClose(true)
    ,isDecodeClose(true)
    ,isAudioClose(true)
    ,isVideoClose(true)
    ,audioStreamIndex(-1)
    ,videoStreamIndex(-1)
    ,eventThread(NULL)
    ,readPackThread(NULL)
    ,decodeThread(NULL)
    ,audioPlayerThread(NULL)
    ,videoPlayerThread(NULL)
{
    if(file)
    {
        filename = (char *)malloc(strlen(file)+1);
        if(filename)
            sprintf(filename,"%s",file);
    }
    else
        filename = NULL;
    avformat_network_init();
    pMutex = SDL_CreateMutex();
    closeOver.allOver = 0;
}
Player::~Player()
{
    if(filename)
        free(filename);
    SDL_DestroyMutex(pMutex);
}
int Player::versionShow(void)
{
    dprintf(VERSION);
    return 0;
}
//同1.0注释，不再赘述
int Player::init(void)
{
    pFormatCtx = avformat_alloc_context();
    ASSERT(pFormatCtx)
    dprintf("filename:%s\n",filename);
	if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_EVENTS)) {  
		dprintf( "Could not initialize SDL - %s\n", SDL_GetError()); 
		return -1;
	}else
    {
        if(avformat_open_input(&pFormatCtx,filename,NULL,NULL)!=0){
            dprintf("Couldn't open input stream.\n");
            return -1;
        }
        if(avformat_find_stream_info(pFormatCtx,NULL)<0){
            dprintf("Couldn't find stream information.\n");
            return -1;
        }
        av_dump_format(pFormatCtx, 0, filename, false);
        eventThread = SDL_CreateThread(eventLoop,"event",(void *)this);
        ASSERT(eventThread)  
        isEventClose = false;      
        readPackThread = SDL_CreateThread(readPackLoop,"readpack",(void *)this);
        ASSERT(readPackThread)
    }
    return 0;
}
int Player::exit(void)
{
    //想要音视频线程结束，直接置标志即可
    if(closeOver.closeSingle.audioOver == 0)
    {
        isAudioClose = true;
    }
    if(closeOver.closeSingle.videoOver == 0)
    {
        isVideoClose = true;
    }
    //解码线程有可能处于等待条件变量的状态，所以结束时先置标志位，再从等待状态唤醒
    if(closeOver.closeSingle.decodeOver == 0)
    {
        if(!isDecodeClose)
        {
            isDecodeClose = true; 
            SDL_LockMutex(pCodec[videoStreamIndex].pFrameQueue->pMutex);
            SDL_CondSignal(pCodec[videoStreamIndex].pFrameQueue->pCond);
            SDL_UnlockMutex(pCodec[videoStreamIndex].pFrameQueue->pMutex);  
            SDL_LockMutex(pCodec[audioStreamIndex].pFrameQueue->pMutex);
            SDL_CondSignal(pCodec[audioStreamIndex].pFrameQueue->pCond);
            SDL_UnlockMutex(pCodec[audioStreamIndex].pFrameQueue->pMutex);     
        }
    }
    //解包线程同上
    if(closeOver.closeSingle.readPacketOver == 0)
    {
        isReadPackClose = true;   
        SDL_LockMutex(packetQueue.pMutex);
        SDL_CondSignal(packetQueue.pCond);
        SDL_UnlockMutex(packetQueue.pMutex);     
    }  
    //按资源依赖顺序释放线程后，阻塞等待线程结束
    while(closeOver.allOver != 0xF);
    SDL_Quit();
    if(pFormatCtx)
    {
        avformat_close_input(&pFormatCtx);
        pFormatCtx = NULL;
    }
    isEventClose = true;
    return 0;
}
int Player::keyEvent(int key)
{
    switch (key)
    {
    case SDLK_SPACE:
        
        break;
    
    default:
        break;
    }
    return 0;
}

int Player::eventLoop(void *pthis)
{
    ASSERT(pthis)
    SDL_Event event;
    Player *tmpthis = (Player *) pthis;
    tmpthis->isEventClose = false;
    while((!tmpthis->isEventClose) && (pthis !=NULL))
    {
        SDL_WaitEvent(&event);
        switch (event.type)
        {
        case SDL_KEYDOWN:
            tmpthis->keyEvent(event.key.keysym.sym);
            break;
        case SDL_QUIT:
            tmpthis->exit();
            break;
        default:
            break;
        }
    }
    dprintf("leave eventLoop\n");
    return 0;
}
//同1.0基本相同，多添加了队列初始化
int Player::codecContextInit(int streamIndex)
{
    dprintf("Init %d\n",streamIndex);
    pCodec[streamIndex].pCodeCtx = avcodec_alloc_context3(NULL);
    ASSERT(pCodec[streamIndex].pCodeCtx)
    avcodec_parameters_to_context(pCodec[streamIndex].pCodeCtx,pFormatCtx->streams[streamIndex]->codecpar);
    pCodec[streamIndex].pCodeCtx->pkt_timebase = pFormatCtx->streams[streamIndex]->time_base;
    pCodec[streamIndex].pAvCodec = avcodec_find_decoder(pCodec[streamIndex].pCodeCtx->codec_id);
    ASSERT(pCodec[streamIndex].pAvCodec)
    if(avcodec_open2(pCodec[streamIndex].pCodeCtx, pCodec[streamIndex].pAvCodec,NULL)<0){
        dprintf("Could not open codec.\n");
        return -1;
    }
    switch (pFormatCtx->streams[streamIndex]->codecpar->codec_type)
    {
    case AVMEDIA_TYPE_VIDEO:
    dprintf("AVMEDIA_TYPE_VIDEO\n");
        videoStreamIndex = streamIndex;
        if(pCodec[streamIndex].pCodeCtx->pix_fmt == AV_PIX_FMT_YUV420P)
        {
            pCodec[streamIndex].pFrame = av_frame_alloc();
            ASSERT(pCodec[streamIndex].pFrame)
            pCodec[streamIndex].videoOutFmt.pOutFrame = av_frame_alloc();
            ASSERT(pCodec[streamIndex].videoOutFmt.pOutFrame)
            pCodec[streamIndex].pBuffer=(unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P,  pCodec[streamIndex].pCodeCtx->width, pCodec[streamIndex].pCodeCtx->height,1));
            ASSERT(pCodec[streamIndex].pBuffer)
            av_image_fill_arrays(pCodec[streamIndex].videoOutFmt.pOutFrame->data, pCodec[streamIndex].videoOutFmt.pOutFrame->linesize,pCodec[streamIndex].pBuffer, \
                AV_PIX_FMT_YUV420P,pCodec[streamIndex].pCodeCtx->width, pCodec[streamIndex].pCodeCtx->height,1);
            pCodec[streamIndex].pSwsConvertCtx = sws_getContext(pCodec[streamIndex].pCodeCtx->width, pCodec[streamIndex].pCodeCtx->height, pCodec[streamIndex].pCodeCtx->pix_fmt, \
            pCodec[streamIndex].pCodeCtx->width, pCodec[streamIndex].pCodeCtx->height,AV_PIX_FMT_YUV420P , SWS_BICUBIC, NULL, NULL, NULL);
            ASSERT(pCodec[streamIndex].pSwsConvertCtx)
        }
        else
        {
            pCodec[streamIndex].pFrame = av_frame_alloc();
            ASSERT(pCodec[streamIndex].pFrame)
            pCodec[streamIndex].videoOutFmt.pOutFrame = av_frame_alloc();
            ASSERT(pCodec[streamIndex].videoOutFmt.pOutFrame)
            pCodec[streamIndex].pBuffer=(unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_RGB24,  pCodec[streamIndex].pCodeCtx->width, pCodec[streamIndex].pCodeCtx->height,1));
            ASSERT(pCodec[streamIndex].pBuffer)
            av_image_fill_arrays(pCodec[streamIndex].videoOutFmt.pOutFrame->data, pCodec[streamIndex].videoOutFmt.pOutFrame->linesize,pCodec[streamIndex].pBuffer, \
                AV_PIX_FMT_RGB24,pCodec[streamIndex].pCodeCtx->width, pCodec[streamIndex].pCodeCtx->height,1);
            pCodec[streamIndex].pSwsConvertCtx = sws_getContext(pCodec[streamIndex].pCodeCtx->width, pCodec[streamIndex].pCodeCtx->height, pCodec[streamIndex].pCodeCtx->pix_fmt, \
            pCodec[streamIndex].pCodeCtx->width, pCodec[streamIndex].pCodeCtx->height,AV_PIX_FMT_RGB24 , SWS_BICUBIC, NULL, NULL, NULL);
            ASSERT(pCodec[streamIndex].pSwsConvertCtx)
        }
        if(screenW<pCodec[streamIndex].pCodeCtx->width)
            screenW = pCodec[streamIndex].pCodeCtx->width;
        if(screenH<pCodec[streamIndex].pCodeCtx->height)
            screenH = pCodec[streamIndex].pCodeCtx->height;
        //初始化frame队列
        pCodec[streamIndex].pFrameQueue = (FrameQueue *)malloc(sizeof(FrameQueue));
        ASSERT(pCodec[streamIndex].pFrameQueue);
        memset(pCodec[streamIndex].pFrameQueue,0,sizeof(FrameQueue));
        //初始化帧队列互斥量
        pCodec[streamIndex].pFrameQueue->pMutex = SDL_CreateMutex();
        //初始化帧队列条件变量
        pCodec[streamIndex].pFrameQueue->pCond = SDL_CreateCond();
        //帧队列最大值
        pCodec[streamIndex].pFrameQueue->maxSize = FRAME_QUEUE_MAX_SIZE;
        //直接为每个帧队列元素申请空间，而非使用时申请
        for(int i=0;i<pCodec[streamIndex].pFrameQueue->maxSize;i++)
        {
            pCodec[streamIndex].pFrameQueue->qFrame[i] = av_frame_alloc();
            ASSERT(pCodec[streamIndex].pFrameQueue->qFrame[i])
        }
        break;
    case AVMEDIA_TYPE_AUDIO:
    dprintf("AVMEDIA_TYPE_AUDIO\n");
        audioStreamIndex = streamIndex;
        pCodec[streamIndex].pAudioOutFmt = (AudioOutFmt *)malloc(sizeof(AudioOutFmt));
        ASSERT(pCodec[streamIndex].pAudioOutFmt)
        memset(pCodec[streamIndex].pAudioOutFmt,0,sizeof(AudioOutFmt));
        pCodec[streamIndex].pAudioOutFmt->outChLayout = AV_CH_LAYOUT_STEREO;
        pCodec[streamIndex].pAudioOutFmt->outNbSamples = pCodec[streamIndex].pCodeCtx->frame_size;
        pCodec[streamIndex].pAudioOutFmt->outNbSampleFmt = AV_SAMPLE_FMT_S16;
        pCodec[streamIndex].pAudioOutFmt->outSamplesRate = pCodec[streamIndex].pCodeCtx->sample_rate;
        pCodec[streamIndex].pAudioOutFmt->outChannels = av_get_channel_layout_nb_channels(pCodec[streamIndex].pAudioOutFmt->outChLayout);
        pCodec[streamIndex].pAudioOutFmt->outFrameSize = av_samples_get_buffer_size(NULL,pCodec[streamIndex].pAudioOutFmt->outChannels ,pCodec[streamIndex].pAudioOutFmt->outNbSamples,pCodec[streamIndex].pAudioOutFmt->outNbSampleFmt, 1);
        pCodec[streamIndex].audioBufCtrl.audioLen = 0;
        pCodec[streamIndex].audioBufCtrl.pAudioChunk = NULL;
        pCodec[streamIndex].audioBufCtrl.pAudioPos = NULL;
        pCodec[streamIndex].pBuffer = (unsigned char *)av_malloc(MAX_AUDIO_FRAME_SIZE*2);
        ASSERT(pCodec[streamIndex].pBuffer)
        pCodec[streamIndex].pFrame = av_frame_alloc();
        ASSERT(pCodec[streamIndex].pFrame)
        //初始化frame队列，同上
        pCodec[streamIndex].pFrameQueue = (FrameQueue *)malloc(sizeof(FrameQueue));
        ASSERT(pCodec[streamIndex].pFrameQueue);
        memset(pCodec[streamIndex].pFrameQueue,0,sizeof(FrameQueue));
        pCodec[streamIndex].pFrameQueue->pMutex = SDL_CreateMutex();
        pCodec[streamIndex].pFrameQueue->pCond = SDL_CreateCond();
        pCodec[streamIndex].pFrameQueue->maxSize = FRAME_QUEUE_MAX_SIZE;
        for(int i=0;i<pCodec[streamIndex].pFrameQueue->maxSize;i++)
        {
            pCodec[streamIndex].pFrameQueue->qFrame[i] = av_frame_alloc();
            ASSERT(pCodec[streamIndex].pFrameQueue->qFrame[i])
        }
        break;
    default:
        break;
    }
    return 0;
}
int Player::codecContextExit(int streamIndex)
{
    if(pCodec != NULL)
    {
        if(pCodec[streamIndex].pCodeCtx != NULL)
        {
            SDL_LockMutex(pMutex);
            avcodec_close(pCodec[streamIndex].pCodeCtx);
            pCodec[streamIndex].pCodeCtx = NULL;
            SDL_UnlockMutex(pMutex);
        }
    }
    return 0;
}
//大部分同1.0相同，不再赘述
int Player::readPackLoop(void *pthis)
{
    ASSERT(pthis)
    Player *tmpthis = (Player *) pthis;
    tmpthis->isReadPackClose = false;
    tmpthis->pCodec = (Codec *)malloc(sizeof(Codec)*(tmpthis->pFormatCtx->nb_streams));
    ASSERT(tmpthis->pCodec)
    memset(tmpthis->pCodec,0,sizeof(Codec)*(tmpthis->pFormatCtx->nb_streams));
 	for(int i=0; i < tmpthis->pFormatCtx->nb_streams; i++)
    {
        if(tmpthis->codecContextInit(i)<0)
        {
            dprintf("Stream%d init failed\n",i);
            return -1;
        }
    }
    //初始化包队列互斥量
    tmpthis->packetQueue.pMutex = SDL_CreateMutex();
    //初始化包队列条件变量
    tmpthis->packetQueue.pCond = SDL_CreateCond();
    //创建其他线程
    tmpthis->decodeThread = SDL_CreateThread(decodeLoop,"decode",(void *)pthis);
    ASSERT(tmpthis->decodeThread)
    tmpthis->isDecodeClose = false;
    tmpthis->audioPlayerThread = SDL_CreateThread(audioLoop,"audio",(void *)pthis);
    ASSERT(tmpthis->audioPlayerThread)
    tmpthis->isAudioClose = false;
    tmpthis->videoPlayerThread = SDL_CreateThread(videoLoop,"video",(void *)pthis);
    ASSERT(tmpthis->videoPlayerThread)
    tmpthis->isVideoClose = false;
    //每次读包存入队列前临时存储
    tmpthis->pPacket = av_packet_alloc();
    ASSERT(tmpthis->pPacket)
    //这两个变量改为局部也行
    tmpthis->gotAudioPicture = -1;
    tmpthis->gotVideoPicture = -1;
   while(!tmpthis->isReadPackClose)
    {   //判断队列是否已满
        if(tmpthis->packetQueue.qPacket.size()<PACKET_QUEUE_MAX_SIZE)
        {
            //未满则读包
            if(av_read_frame(tmpthis->pFormatCtx, tmpthis->pPacket) == 0)
            {
                //存入队列前要上锁
                SDL_LockMutex(tmpthis->packetQueue.pMutex);
                //申请一个包变量
                AVPacket *tmppacket = av_packet_alloc();
                if (!tmppacket) {
                    dprintf("tmppacket malloc failed\n");
                    av_packet_unref(tmppacket);
                    return -1;
                }
                //把取到的包存入新申请的包变量
                av_packet_move_ref(tmppacket, tmpthis->pPacket);
                //入队
                tmpthis->packetQueue.qPacket.push(tmppacket);
                SDL_UnlockMutex(tmpthis->packetQueue.pMutex);
                //临时存包的变量可以释放，等待下次存储
                av_packet_unref(tmpthis->pPacket);
            }
            //队列没满但是读取包失败了，则认为包已经被读取完了，线程结束
            else
            {
                tmpthis->isReadPackClose = true;
                dprintf("readPacket Over\n");
            }
        }
        //队列已经满了则等待条件变量，此条件在解码线程每次从包队列里取出一个包就满足一次
        else
        {
            SDL_LockMutex(tmpthis->packetQueue.pMutex);
            SDL_CondWait(tmpthis->packetQueue.pCond,tmpthis->packetQueue.pMutex);
            SDL_UnlockMutex(tmpthis->packetQueue.pMutex);
        }
    }
    dprintf("leave readPackLoop\n");
    //因为包队列元素空间释放在解码线程，所以解包线程要退出，必须等待解码线程退出，以保证队列里所有包资源都已被释放
    while(tmpthis->closeOver.closeSingle.decodeOver == 0);
    if(tmpthis->pCodec)
    {
        free(tmpthis->pCodec);
        tmpthis->pCodec = NULL;        
    }
    SDL_DestroyMutex(tmpthis->packetQueue.pMutex);
    SDL_DestroyCond(tmpthis->packetQueue.pCond);
    av_packet_free(&tmpthis->pPacket);
    tmpthis->pPacket = NULL;
    tmpthis->codecContextExit(tmpthis->audioStreamIndex);
    tmpthis->codecContextExit(tmpthis->videoStreamIndex);
    tmpthis->isReadPackClose = true;
    tmpthis->closeOver.closeSingle.readPacketOver = 1;
    dprintf("readPackLoop free over\n");
    return 0;
}
int Player::decodeLoop(void *pthis)
{
    ASSERT(pthis)
    Player *tmpthis = (Player *)pthis; 
    tmpthis->isDecodeClose = false;
    while (!tmpthis->isDecodeClose)
    {
        //判断包队列是否有元素可取
        if(tmpthis->packetQueue.qPacket.size()>0)
        {
            //有元素可取，操作前先上锁
            SDL_LockMutex(tmpthis->packetQueue.pMutex);
            //取首个元素
            AVPacket *tmpPacket = tmpthis->packetQueue.qPacket.front();
            //从队列中弹出，即size-1，但是资源未释放
            tmpthis->packetQueue.qPacket.pop();
            //判断包类型
            switch (tmpthis->pFormatCtx->streams[tmpPacket->stream_index]->codecpar->codec_type)
            {
            case AVMEDIA_TYPE_AUDIO:
                tmpthis->audioStreamIndex = tmpPacket->stream_index;
                avcodec_send_packet(tmpthis->pCodec[tmpthis->audioStreamIndex].pCodeCtx,tmpPacket);
                //释放包资源
                av_packet_free(&tmpPacket);
                //置位条件
                SDL_CondSignal(tmpthis->packetQueue.pCond);
                SDL_UnlockMutex(tmpthis->packetQueue.pMutex);
                //判断帧队列是否已满
                if(tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->qSize >= tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->maxSize)
                {
                    //帧队列满了，则等待条件变量，此变量在对应播放线程被满足
                    SDL_LockMutex(tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->pMutex);    
                    SDL_CondWait(tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->pCond,tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->pMutex);
                    SDL_UnlockMutex(tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->pMutex);      
                }
                //条件被满足后，证明帧队列已经被取走一个元素
                SDL_LockMutex(tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->pMutex);  
                //判断写索引是否需要从头开始 
                if(tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->writePrt > tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->maxSize-1)
                {
                    tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->writePrt = 0;
                }
                //解码
                tmpthis->gotAudioPicture = avcodec_receive_frame(tmpthis->pCodec[tmpthis->audioStreamIndex].pCodeCtx,
                tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->qFrame[tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->writePrt]); 
                if(tmpthis->gotAudioPicture == 0)
                {
                    //解码成功后队列size+1，写索引+1
                    tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->qSize++;
                    tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->writePrt++;
                }
                SDL_UnlockMutex(tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->pMutex);
                break;
            case AVMEDIA_TYPE_VIDEO:
                //同上
                tmpthis->videoStreamIndex = tmpPacket->stream_index;
                avcodec_send_packet(tmpthis->pCodec[tmpthis->videoStreamIndex].pCodeCtx,tmpPacket);
                av_packet_free(&tmpPacket);
                SDL_CondSignal(tmpthis->packetQueue.pCond);
                SDL_UnlockMutex(tmpthis->packetQueue.pMutex);

                if(tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->qSize >= tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->maxSize)
                {
                    SDL_LockMutex(tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->pMutex);     
                    SDL_CondWait(tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->pCond,tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->pMutex);
                    SDL_UnlockMutex(tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->pMutex);      
                }
                SDL_LockMutex(tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->pMutex);  
                if(tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->writePrt>tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->maxSize-1)
                {
                    tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->writePrt = 0;
                }   
                tmpthis->gotVideoPicture = avcodec_receive_frame(tmpthis->pCodec[tmpthis->videoStreamIndex].pCodeCtx,
                tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->qFrame[tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->writePrt]); 
                if(tmpthis->gotVideoPicture == 0)
                {
                    tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->qSize++;
                    tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->writePrt++;
                }
                SDL_UnlockMutex(tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->pMutex);
                break;
            default:
                break;
            }
        }
        else
        {
            if(tmpthis->isReadPackClose)
            {
                tmpthis->isDecodeClose = true;
                dprintf("isDecodeClose is true\n");
            }
        }
    }
    dprintf("leave decodeLoop\n");
    //等待音频与视频线程结束，防止使用帧时异常
    while(!((tmpthis->closeOver.closeSingle.audioOver==1) && (tmpthis->closeOver.closeSingle.videoOver==1)));
    //释放包队列所有元素
    if(tmpthis->packetQueue.qPacket.size()>0)
    {
        for(int i=0;i<tmpthis->packetQueue.qPacket.size();i++)
        {
            AVPacket *tmpPacket = tmpthis->packetQueue.qPacket.front();
            av_packet_free(&tmpPacket);
            tmpPacket = NULL;
            tmpthis->packetQueue.qPacket.pop();           
        }
    }
    //释放音频帧队列所有元素
    for(int z = 0;z<tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->maxSize;z++)
    {
        av_frame_free(&tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->qFrame[z]);
        tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->qFrame[z] = NULL;
        tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->maxSize = 0;
        tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->qSize = 0;
    }
    SDL_DestroyMutex(tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->pMutex);
    SDL_DestroyCond(tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->pCond);
    //释放视频帧队列所有元素
    for(int z = 0;z<tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->maxSize;z++)
    {
        av_frame_free(&tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->qFrame[z]);
        tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->qFrame[z] = NULL;
        tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->maxSize = 0;
        tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->qSize = 0;
    }
    SDL_DestroyMutex(tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->pMutex);
    SDL_DestroyCond(tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->pCond);
    
    av_frame_free(&tmpthis->pCodec[tmpthis->audioStreamIndex].pFrame);
    tmpthis->pCodec[tmpthis->audioStreamIndex].pFrame = NULL;
    av_frame_free(&tmpthis->pCodec[tmpthis->videoStreamIndex].pFrame);
    tmpthis->pCodec[tmpthis->videoStreamIndex].pFrame = NULL;
    tmpthis->isDecodeClose = true;
    tmpthis->closeOver.closeSingle.decodeOver = 1;
    dprintf("decodeLoop free over\n");
    return 0;
}
//同1.0
void Player::audioCallBack(void *pthis,unsigned char *stream,int len)
{
    if(pthis == NULL)
        return;
    Player *tmpthis = (Player *)pthis;
    SDL_memset(stream, 0, len);
	if(tmpthis->pCodec[tmpthis->audioStreamIndex].audioBufCtrl.audioLen == 0)
		return; 
	len=(len>tmpthis->pCodec[tmpthis->audioStreamIndex].audioBufCtrl.audioLen?tmpthis->pCodec[tmpthis->audioStreamIndex].audioBufCtrl.audioLen:len);
	memcpy(stream, tmpthis->pCodec[tmpthis->audioStreamIndex].audioBufCtrl.pAudioPos, len);
	tmpthis->pCodec[tmpthis->audioStreamIndex].audioBufCtrl.pAudioPos += len; 
	tmpthis->pCodec[tmpthis->audioStreamIndex].audioBufCtrl.audioLen -= len; 
}
int Player::audioLoop(void *pthis)
{
    ASSERT(pthis)
    Player *tmpthis = (Player *)pthis; 
    tmpthis->isAudioClose = false;
    SDL_AudioSpec audioSpec;
    int i = tmpthis->audioStreamIndex;
    audioSpec.freq = tmpthis->pCodec[i].pAudioOutFmt->outSamplesRate;
    audioSpec.format = AUDIO_S16SYS;
    audioSpec.channels = tmpthis->pCodec[i].pAudioOutFmt->outChannels;
    audioSpec.silence = 0;
    audioSpec.samples = tmpthis->pCodec[i].pAudioOutFmt->outNbSamples;
    audioSpec.callback = audioCallBack;
    audioSpec.userdata = pthis;
	if (SDL_OpenAudio(&audioSpec, NULL)<0){ 
		dprintf("can't open audio.\n"); 
		return -1; 
	} 
    tmpthis->pCodec[i].pSwrConvertCtx = swr_alloc();
    ASSERT(tmpthis->pCodec[i].pSwrConvertCtx)
	tmpthis->pCodec[i].pSwrConvertCtx=swr_alloc_set_opts(tmpthis->pCodec[i].pSwrConvertCtx, \
    tmpthis->pCodec[i].pAudioOutFmt->outChLayout,                                                                                                \
    tmpthis->pCodec[i].pAudioOutFmt->outNbSampleFmt,                                                                                      \
    tmpthis->pCodec[i].pAudioOutFmt->outSamplesRate,                                                                                         \
    av_get_default_channel_layout(tmpthis->pCodec[i].pCodeCtx->channels),                                           \
    tmpthis->pCodec[i].pCodeCtx->sample_fmt ,                                                                                                         \
    tmpthis->pCodec[i].pCodeCtx->sample_rate,0, NULL);
	swr_init(tmpthis->pCodec[i].pSwrConvertCtx);   
    SDL_PauseAudio(0);
    while(!tmpthis->isAudioClose)
    {
        //判断是否有帧可取
        if(tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->qSize>0)
        {
            //有帧可取，则根据读索引，直接使用帧队列元素
            SDL_LockMutex(tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->pMutex);     
            swr_convert(tmpthis->pCodec[tmpthis->audioStreamIndex].pSwrConvertCtx,   \
            &tmpthis->pCodec[tmpthis->audioStreamIndex].pBuffer,                                                 \
            MAX_AUDIO_FRAME_SIZE,                                                                                            \
            (const uint8_t **)tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->qFrame[tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->readPrt]->data, \
            tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->qFrame[tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->readPrt]->nb_samples);      
            tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->readPrt++;
            if(tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->readPrt>tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->maxSize-1)
                tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->readPrt = 0; 
            tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->qSize--;
            SDL_CondSignal(tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->pCond);
            SDL_UnlockMutex(tmpthis->pCodec[tmpthis->audioStreamIndex].pFrameQueue->pMutex);    
            while(tmpthis->pCodec[tmpthis->audioStreamIndex].audioBufCtrl.audioLen>0)
            {
                SDL_Delay(1); 
            }
            tmpthis->pCodec[tmpthis->audioStreamIndex].audioBufCtrl.pAudioChunk = tmpthis->pCodec[tmpthis->audioStreamIndex].pBuffer; 
            tmpthis->pCodec[tmpthis->audioStreamIndex].audioBufCtrl.audioLen =tmpthis->pCodec[tmpthis->audioStreamIndex].pAudioOutFmt->outFrameSize;
            tmpthis->pCodec[tmpthis->audioStreamIndex].audioBufCtrl.pAudioPos = tmpthis->pCodec[tmpthis->audioStreamIndex].audioBufCtrl.pAudioChunk;                 
        }  

    }
    dprintf("leave audioLoop\n");
    if(tmpthis->pCodec[tmpthis->audioStreamIndex].pAudioOutFmt!=NULL)
    {
        free(tmpthis->pCodec[tmpthis->audioStreamIndex].pAudioOutFmt);
        tmpthis->pCodec[tmpthis->audioStreamIndex].pAudioOutFmt = NULL;
    }
    swr_free(&tmpthis->pCodec[tmpthis->audioStreamIndex].pSwrConvertCtx);
    tmpthis->pCodec[tmpthis->audioStreamIndex].pSwrConvertCtx = NULL;
    av_free(tmpthis->pCodec[tmpthis->audioStreamIndex].pBuffer);
    tmpthis->pCodec[tmpthis->audioStreamIndex].pBuffer = NULL;
    SDL_CloseAudio();
    tmpthis->isAudioClose = true;
    tmpthis->closeOver.closeSingle.audioOver = 1;
    dprintf("audioLoop free over\n");
    return 0;
}
//同音频线程处理方式
int Player::videoLoop(void *pthis)
{
    ASSERT(pthis)
    Player *tmpthis = (Player *)pthis; 
    tmpthis->isVideoClose = false;
    SDL_Window *screen;
    screen = SDL_CreateWindow("Player",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,\
    tmpthis->screenW,tmpthis->screenH,SDL_WINDOW_SHOWN);
    if(!screen)
    {
        dprintf("Can't Create Window -- %s\n",SDL_GetError());
        return -1;
    }
    SDL_Renderer* sdlRenderer = SDL_CreateRenderer(screen, -1, 0);
    SDL_RenderClear(sdlRenderer);
    SDL_Texture* sdlTexture = NULL;
    if(tmpthis->pCodec[tmpthis->videoStreamIndex].pCodeCtx->pix_fmt == AV_PIX_FMT_YUV420P)
        sdlTexture = SDL_CreateTexture(sdlRenderer,SDL_PIXELFORMAT_IYUV,\
        SDL_TEXTUREACCESS_STREAMING,tmpthis->screenW,tmpthis->screenH);//SDL_PIXELFORMAT_RGB24 /SDL_PIXELFORMAT_IYUV
    else
        sdlTexture = SDL_CreateTexture(sdlRenderer,SDL_PIXELFORMAT_RGB24,\
        SDL_TEXTUREACCESS_STREAMING,tmpthis->screenW,tmpthis->screenH);//SDL_PIXELFORMAT_RGB24 /SDL_PIXELFORMAT_IYUV
	SDL_Rect sdlRect;
    sdlRect.h = tmpthis->screenH;
    sdlRect.w = tmpthis->screenW;
    while(!tmpthis->isVideoClose)
    {
        if(tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->qSize>0)
        {
            SDL_LockMutex(tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->pMutex); 
            sws_scale(tmpthis->pCodec[tmpthis->videoStreamIndex].pSwsConvertCtx, 
            (const unsigned char* const*)tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->qFrame[tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->readPrt]->data, 
            tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->qFrame[tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->readPrt]->linesize, 
            0, 
            tmpthis->pCodec[tmpthis->videoStreamIndex].pCodeCtx->height, 
            tmpthis->pCodec[tmpthis->videoStreamIndex].videoOutFmt.pOutFrame->data, 
            tmpthis->pCodec[tmpthis->videoStreamIndex].videoOutFmt.pOutFrame->linesize);

            tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->readPrt++;
            if(tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->readPrt>tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->maxSize-1)
                tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->readPrt = 0; 
            tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->qSize--;         
            SDL_CondSignal(tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->pCond);   
            SDL_UnlockMutex(tmpthis->pCodec[tmpthis->videoStreamIndex].pFrameQueue->pMutex);   
            SDL_UpdateTexture( sdlTexture, &sdlRect,                                                                                            \
            tmpthis->pCodec[tmpthis->videoStreamIndex].videoOutFmt.pOutFrame->data[0],         \
            tmpthis->pCodec[tmpthis->videoStreamIndex].videoOutFmt.pOutFrame->linesize[0] ); \
            SDL_RenderClear( sdlRenderer );  
            SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, &sdlRect);  
            SDL_RenderPresent( sdlRenderer ); 
            tmpthis->gotVideoPicture = -1;             
        }
    }
    dprintf("leave videoLoop\n");
    av_free(tmpthis->pCodec[tmpthis->videoStreamIndex].pBuffer);
    tmpthis->pCodec[tmpthis->videoStreamIndex].pBuffer = NULL;
    av_frame_free(&tmpthis->pCodec[tmpthis->videoStreamIndex].videoOutFmt.pOutFrame);
    tmpthis->pCodec[tmpthis->videoStreamIndex].videoOutFmt.pOutFrame = NULL;
    sws_freeContext(tmpthis->pCodec[tmpthis->videoStreamIndex].pSwsConvertCtx);
    tmpthis->pCodec[tmpthis->videoStreamIndex].pSwsConvertCtx = NULL;
    tmpthis->isVideoClose = true;
    tmpthis->closeOver.closeSingle.videoOver = 1;
    SDL_DestroyWindow(screen);
    dprintf("videoLoop free over\n");
    return 0;
}